/******************************************************************
 *
 *    Java Lib For JavaWeb, Powered By Zhejiang hangzhou.
 *
 *    Copyright (c) 2001-2020
 *    http://tankpao.tk/
 *
 *    Package:     tk.tankpao.blast.core.aop
 *
 *    Filename:    BaseInterceptor.java
 *
 *    Description: TODO(用一句话描述该文件做什么)
 *
 *    Copyright:   Copyright (c) 2001-2020
 *
 *    Company:     tankpao.tk
 *
 *    @author:     王志刚
 *
 *    @version:    1.0.0
 *
 *    Create at:   2017年2月9日 下午2:46:10
 *
 *    Revision:
 *
 *    2017年2月9日 下午2:46:10
 *        - first revision
 *
 *****************************************************************/
package tk.tankpao.blast.core.aop;

import java.lang.reflect.Method;
import java.util.Map;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import tk.tankpao.blast.core.annotation.Pointcut;
import tk.tankpao.blast.util.PointcutPathUtils;

/**
 * 
 * @ClassName BaseInterceptor
 * @Description 拦截类
 * @author 王志刚
 * @Date 2017年2月9日 下午2:47:20
 * @version 1.0.0
 */
public abstract class BaseInterceptor implements MethodInterceptor {
	/**
	 * 父类对象
	 */
	private Object targetObj;
	private Map<String,Boolean> exeFlagMap = null; 

	@Override
	final public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		initExecuteFlag();
		doBeforeRunning(targetObj, method, args);
		Object object = proxy.invoke(targetObj, args);
		doAfterReturning(targetObj, method, args, object);
		return object;
	}
	
	private void initExecuteFlag(){
		if(exeFlagMap == null){
			synchronized(targetObj) {
				if(exeFlagMap == null){
					Pointcut pointcut = this.getClass().getAnnotation(Pointcut.class);
					String path = pointcut.path();
					exeFlagMap = PointcutPathUtils.accordMethods(path, targetObj);
				}
			}
		}
	}

	public boolean executeFlag(String methodName) {
		String key = targetObj.getClass().getName()+"."+methodName;
		return exeFlagMap.get(key) == null ? false : exeFlagMap.get(key);
	}

	
	public void doBeforeRunning(Object target, Method method, Object[] args) throws Throwable {
		if(executeFlag(method.getName())){
			beforeRunning(targetObj, method, args);
		}
	}

	public void doAfterReturning(Object target, Method method, Object[] args, Object returnValue) throws Throwable {
		if(executeFlag(method.getName())){
			afterReturning(targetObj, method, args, returnValue);
		}
	}

	public abstract void beforeRunning(Object target, Method method, Object[] args) throws Throwable;

	public abstract void afterReturning(Object target, Method method, Object[] args, Object returnValue) throws Throwable;

	public Object getTargetObj() {
		return targetObj;
	}

	public void setTargetObj(Object targetObj) {
		this.targetObj = targetObj;
	}

}
